/*
 * Copyright 2007 Matt Jensen
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.jtell.internal;

import java.util.Collection;

/**
 * <p>
 * <code>Guard</code> is a utility class which provides methods for guarding against invalid method arguments.
 * </p>
 */
public class Guard
{
    /**
     * <p>
     * Construct a {@link Guard} instance.
     * </p>
     */
    private Guard()
    {
        super();
    }

    /**
     * <p>
     * Guard against a null argument.
     * </p>
     *
     * @param name the argument name.
     * @param value the argument value.
     * @throws NullPointerException if the value is null.
     */
    public static void notNull(final String name, final Object value) throws NullPointerException
    {
        if (null == value)
        {
            throw new NullPointerException(String.format("The [%s] argument cannot be null.", name));
        }
    }

    /**
     * <p>
     * Guard against an argument which is not of an appropriate type.
     * </p>
     *
     * @param name the argument name.
     * @param clazz the expected class.
     * @param value the argument value.
     * @throws IllegalArgumentException if the value does not extend or implement the expected class.
     */
    public static <T> void instanceOf(final String name, final Class<? extends T> clazz, final T value)
            throws IllegalArgumentException
    {
        Guard.notNull("name", name);
        Guard.notNull("clazz", clazz);
        if (!clazz.isInstance(value))
        {
            throw new IllegalArgumentException(String.format("The [%s] argument must be assignable to [%s].", name,
                    clazz));
        }
    }

    /**
     * <p>
     * Guard against a <code>null</code> or empty collection.
     * </p>
     *
     * @param name the argument name.
     * @param value the argument value.
     * @throws NullPointerException if the value is null.
     * @throws IllegalArgumentException if the value is an empty collection.
     */
    public static void notNullOrEmpty(final String name, final Collection<?> value) throws IllegalArgumentException
    {
        Guard.notNull(name, value);
        if (value.isEmpty())
        {
            throw new IllegalArgumentException(String.format("The [%s] argument must be a non-empty collection.",
                    name));
        }
    }

    /**
     * <p>
     * Guard against a <code>null</code> bean property.
     * </p>
     *
     * @param name the property name.
     * @param value the property value.
     * @throws IllegalStateException if the value is <code>null</code>.
     */
    public static void propertyNotNull(final String name, final Object value) throws IllegalStateException
    {
        if (null == value)
        {
            throw new IllegalStateException(String.format("The [%s] property cannot be null.", name));
        }
    }

    /**
     * <p>
     * Guard against resetting of a bean property.
     * </p>
     *
     * @param name the property name.
     * @param value the property value.
     * @throws IllegalStateException if the property has already been set.
     */
    public static void propertyNull(final String name, final Object value) throws IllegalStateException
    {
        if (null != value)
        {
            throw new IllegalStateException(String.format("The [%s] property has already been set to [%s].", name,
                    value));
        }
    }
}
